home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Environments / PowerMacOberon feb96 / Source / GraphicFrames.Mod (.txt) < prev    next >
Encoding:
Oberon Text  |  1995-02-14  |  18.0 KB  |  498 lines  |  [TEXT/.Ob4]

  1. Syntax10.Scn.Fnt
  2. MODULE GraphicFrames; (*NW 18.4.88 / 22.11.91*)    (* << RC 23.12.92 *)
  3.     IMPORT Display, Viewers, Input, Fonts, Texts, Graphics, Oberon, MenuViewers;
  4.     CONST (*update message ids*)
  5.         restore = 0;
  6.         drawobj = 1; drawobjs = 2; drawobjd = 3;
  7.         drawnorm = 4; drawsel = 5; drawdel = 6;
  8.         markW = 5;
  9.     TYPE
  10.         Frame* = POINTER TO FrameDesc;
  11.         Location* = POINTER TO LocDesc;
  12.         LocDesc* = RECORD
  13.                 x*, y*: INTEGER;
  14.                 next*: Location
  15.             END ;
  16.         FrameDesc* = RECORD (Display.FrameDesc)
  17.                 graph*: Graphics.Graph;
  18.                 Xg*, Yg*: INTEGER;  (*pos rel to graph origin*)
  19.                 X1*, Y1*: INTEGER;  (*right and upper margins*)
  20.                 x*, y*, col*: INTEGER;  (*x = X + Xg, y = Y + Yg*)
  21.                 marked*, ticked*: BOOLEAN;
  22.                 mark*: LocDesc
  23.             END ;
  24.         DrawMsg* = RECORD (Graphics.Msg)
  25.                 f*: Frame;
  26.                 x*, y*, col*, mode*: INTEGER
  27.             END ;
  28.         CtrlMsg* = RECORD (Graphics.Msg)
  29.                 f*: Frame;
  30.                 res*: INTEGER
  31.             END ;
  32.         UpdateMsg = RECORD (Display.FrameMsg)
  33.                 id: INTEGER;
  34.                 graph: Graphics.Graph;
  35.                 obj: Graphics.Object
  36.             END ;
  37.         SelQuery = RECORD (Display.FrameMsg)
  38.                 f: Frame; time: LONGINT
  39.             END ;
  40.         FocusQuery = RECORD (Display.FrameMsg)
  41.                 f: Frame
  42.             END ;
  43.         PosQuery = RECORD (Display.FrameMsg)
  44.                 f: Frame; x, y: INTEGER
  45.             END ;
  46.         DispMsg = RECORD (Display.FrameMsg)
  47.                 x1, y1, w: INTEGER;
  48.                 pat: Display.Pattern;
  49.                 graph: Graphics.Graph
  50.             END ;
  51.     VAR Crosshair*: Oberon.Marker;
  52.         newcap: Graphics.Caption;
  53.         DW, DH, CL: INTEGER;
  54.         W: Texts.Writer;
  55.     (*Exported procedures:
  56.         Restore, Focus, Selected, This, Draw, DrawNorm, Erase,
  57.         DrawObj, EraseObj, Change, Defocus, Deselect, Macro, New*)
  58.     PROCEDURE Restore*(F: Frame);
  59.         VAR M: DrawMsg; x, y, col: INTEGER;
  60.     BEGIN F.X1 := F.X + F.W; F.Y1 := F.Y + F.H;
  61.         F.x := F.X + F.Xg; F.y := F.Y1 + F.Yg; F.marked := FALSE; F.mark.next := NIL;
  62.         IF F.X < CL THEN col := Display.black ELSE col := F.col END ;
  63.         Oberon.RemoveMarks(F.X, F.Y, F.W, F.H);
  64.         Display.ReplConst(col, F.X, F.Y, F.W, F.H, 0);
  65.         IF F.ticked THEN
  66.             y := F.Yg MOD 16 + F.Y1 - 16;
  67.             WHILE y >= F.Y DO (*draw ticks*)
  68.                 x := F.Xg MOD 16 + F.X;
  69.                 WHILE x < F.X1 DO Display.Dot(Display.white, x, y, 0); INC(x, 16) END ;
  70.                 DEC(y, 16)
  71.             END
  72.         END ;
  73.         M.f := F; M.x := F.x; M.y := F.y; M.col := 0; M.mode := 0; Graphics.Draw(F.graph, M)
  74.     END Restore;
  75.     PROCEDURE Focus*(): Frame;
  76.         VAR FQ: FocusQuery;
  77.     BEGIN FQ.f := NIL; Viewers.Broadcast(FQ); RETURN FQ.f
  78.     END Focus;
  79.     PROCEDURE Selected*(): Frame;
  80.         VAR SQ: SelQuery;
  81.     BEGIN SQ.f := NIL; SQ.time := 0; Viewers.Broadcast(SQ); RETURN SQ.f
  82.     END Selected;
  83.     PROCEDURE This*(x, y: INTEGER): Frame;
  84.         VAR PQ: PosQuery;
  85.     BEGIN PQ.f := NIL; PQ.x := x; PQ.y := y; Viewers.Broadcast(PQ); RETURN PQ.f
  86.     END This;
  87.     PROCEDURE Draw*(F: Frame);
  88.         VAR UM: UpdateMsg;
  89.     BEGIN UM.id := drawsel; UM.graph := F.graph; Viewers.Broadcast(UM)
  90.     END Draw;
  91.     PROCEDURE DrawNorm(F: Frame);
  92.         VAR UM: UpdateMsg;
  93.     BEGIN UM.id := drawnorm; UM.graph := F.graph; Viewers.Broadcast(UM)
  94.     END DrawNorm;
  95.     PROCEDURE Erase*(F: Frame);
  96.         VAR UM: UpdateMsg;
  97.     BEGIN UM.id := drawdel; UM.graph := F.graph; Viewers.Broadcast(UM)
  98.     END Erase;
  99.     PROCEDURE DrawObj*(F: Frame; obj: Graphics.Object);
  100.         VAR UM: UpdateMsg;
  101.     BEGIN UM.id := drawobj; UM.graph := F.graph; UM.obj := obj; Viewers.Broadcast(UM)
  102.     END DrawObj;
  103.     PROCEDURE EraseObj*(F: Frame; obj: Graphics.Object);
  104.         VAR UM: UpdateMsg;
  105.     BEGIN UM.id := drawobjd; UM.graph := F.graph; UM.obj := obj; Viewers.Broadcast(UM)
  106.     END EraseObj;
  107.     PROCEDURE Change*(F: Frame; VAR msg: Graphics.Msg);
  108.     BEGIN
  109.         IF F # NIL THEN Erase(F); Graphics.Handle(F.graph, msg); Draw(F) END
  110.     END Change;
  111.     PROCEDURE FlipMark(x, y: INTEGER);
  112.     BEGIN
  113.         Display.ReplConst(Display.white, x-7, y, 15, 1, 2);
  114.         Display.ReplConst(Display.white, x, y-7, 1, 15, 2)
  115.     END FlipMark;
  116.     PROCEDURE Defocus*(F: Frame);
  117.         VAR m: Location;
  118.     BEGIN newcap := NIL;
  119.         IF F.marked THEN
  120.             FlipMark(F.mark.x, F.mark.y); m := F.mark.next;
  121.             WHILE m # NIL DO FlipMark(m.x, m.y); m := m.next END ;
  122.             F.marked := FALSE; F.mark.next := NIL
  123.         END
  124.     END Defocus;
  125.     PROCEDURE Deselect*(F: Frame);
  126.         VAR UM: UpdateMsg;
  127.     BEGIN
  128.         IF F # NIL THEN
  129.             UM.id := drawnorm; UM.graph := F.graph; Viewers.Broadcast(UM);
  130.             Graphics.Deselect(F.graph)
  131.         END
  132.     END Deselect;
  133.     PROCEDURE Macro*(VAR Lname, Mname: ARRAY OF CHAR);
  134.         VAR x, y: INTEGER;
  135.             F: Frame;
  136.             mac: Graphics.Macro; mh: Graphics.MacHead;
  137.             L: Graphics.Library;
  138.     BEGIN F := Focus();
  139.         IF F # NIL THEN
  140.             x := F.mark.x - F.x; y := F.mark.y - F.y;
  141.             L := Graphics.ThisLib(Lname, FALSE);
  142.             IF L # NIL THEN
  143.                 mh := Graphics.ThisMac(L, Mname);
  144.                 IF mh # NIL THEN
  145.                     Deselect(F); Defocus(F);
  146.                     NEW(mac); mac.x := x; mac.y := y; mac.w := mh.w; mac.h := mh.h;
  147.                     mac.mac := mh; mac.do := Graphics.MacMethod; mac.col := Oberon.CurCol;
  148.                     Graphics.Add(F.graph, mac); DrawObj(F, mac)
  149.                 END
  150.             END
  151.         END
  152.     END Macro;
  153.     PROCEDURE CaptionCopy(F: Frame;
  154.             x1, y1: INTEGER; T: Texts.Text; beg, end: LONGINT): Graphics.Caption;
  155.         VAR ch: CHAR;
  156.             dx, w, x2, y2, w1, h1: INTEGER;
  157.             cap: Graphics.Caption;
  158.             pat: Display.Pattern;
  159.             R: Texts.Reader;
  160.     BEGIN Texts.Write(W, 0DX);
  161.         NEW(cap); cap.len := SHORT(end - beg);
  162.         cap.pos := SHORT(Graphics.T.len)+1; cap.do := Graphics.CapMethod;
  163.         Texts.OpenReader(R, T, beg); Texts.Read(R, ch); W.fnt := R.fnt; W.col := R.col; w := 0;
  164.         cap.x := x1 - F.x; cap.y := y1 - F.y + R.fnt.minY;
  165.         WHILE beg < end DO
  166.             Display.GetChar(R.fnt.raster, ch, dx, x2, y2, w1, h1, pat);
  167.             INC(w, dx); INC(beg); Texts.Write(W, ch); Texts.Read(R, ch)
  168.         END ;
  169.         cap.w := w; cap.h := W.fnt.height; cap.col := W.col;
  170.         Texts.Append(Graphics.T, W.buf); Graphics.Add(F.graph, cap); RETURN cap
  171.     END CaptionCopy;
  172.     PROCEDURE SendCaption(cap: Graphics.Caption);
  173.         VAR M: Oberon.CopyOverMsg;
  174.     BEGIN
  175.         M. text := Graphics.T; M.beg := cap.pos; M.end := M.beg + cap.len; Viewers.Broadcast(M)
  176.     END SendCaption;
  177.     PROCEDURE Edit(F: Frame; x0, y0: INTEGER; k0: SET);
  178.         VAR obj: Graphics.Object;
  179.             x1, y1, w, h, t: INTEGER;
  180.             beg, end, time: LONGINT;
  181.             k1, k2: SET;
  182.             mark, newmark: Location;
  183.             T: Texts.Text;
  184.             Fd: Frame;
  185.             G: Graphics.Graph;
  186.             CM: CtrlMsg;
  187.         PROCEDURE NewLine(x, y, w, h: INTEGER);
  188.             VAR line: Graphics.Line;
  189.         BEGIN NEW(line); line.col := Oberon.CurCol; line.x := x - F.x; line.y := y - F.y;
  190.             line.w := w; line.h := h; line.do := Graphics.LineMethod; Graphics.Add(G, line)
  191.         END NewLine;
  192.     BEGIN k1 := k0; G := F.graph;
  193.         IF k0 = {1} THEN
  194.             obj := Graphics.ThisObj(G, x0 - F.x, y0 - F.y);
  195.             IF (obj # NIL) & ~obj.selected THEN
  196.                 CM.f := F; CM.res := 0; obj.do.handle(obj, CM);
  197.                 IF CM.res # 0 THEN (*done*) k0 := {} END
  198.             END
  199.         END ;
  200.         REPEAT Input.Mouse(k2, x1, y1); k1 := k1 + k2;
  201.             INC(x1, (F.x-x1) MOD 4); INC(y1, (F.y-y1) MOD 4);
  202. (*            DEC(x1, (x1-F.x) MOD 4); DEC(y1, (y1-F.y) MOD 4); *)
  203.             Oberon.DrawCursor(Oberon.Mouse, Crosshair, x1, y1)
  204.         UNTIL  k2 = {};
  205.         Oberon.FadeCursor(Oberon.Mouse);
  206.         IF k0 = {2} THEN (*left key*)
  207.             w := ABS(x1-x0); h := ABS(y1-y0);
  208.             IF k1 = {2} THEN
  209.                 IF (w < 7) & (h < 7) THEN (*set mark*)
  210.                     IF (x1 - markW >= F.X) & (x1 + markW < F.X1) &
  211.                         (y1 - markW >= F.Y) & (y1 + markW < F.Y1) THEN
  212.                         Defocus(F); Oberon.PassFocus(Viewers.This(F.X, F.Y));
  213.                         F.mark.x := x1; F.mark.y := y1; F.marked := TRUE; FlipMark(x1, y1)
  214.                     END
  215.                 ELSE (*draw line*) Deselect(F);
  216.                     IF w < h THEN
  217.                         IF y1 < y0 THEN y0 := y1 END ;
  218.                         NewLine(x0, y0, Graphics.width, h)
  219.                     ELSE
  220.                         IF x1 < x0 THEN x0 := x1 END ;
  221.                         NewLine(x0, y0, w, Graphics.width)
  222.                     END ;
  223.                     Draw(F)
  224.                 END
  225.             ELSIF k1 = {2, 1} THEN (*copy selection to caret mark*)
  226.                 Deselect(F); Oberon.GetSelection(T, beg, end, time);
  227.                 IF time >= 0 THEN DrawObj(F, CaptionCopy(F, x1, y1, T, beg, end)) END
  228.             ELSIF k1 = {2, 0} THEN
  229.                 IF F.marked THEN (*set secondary mark*)
  230.                         NEW(newmark); newmark.x := x1; newmark.y := y1; newmark.next := NIL;
  231.                     FlipMark(x1, y1); mark := F.mark.next;
  232.                     IF mark = NIL THEN F.mark.next := newmark ELSE
  233.                         WHILE mark.next # NIL DO mark := mark.next END ;
  234.                         mark.next := newmark
  235.                     END
  236.                 END
  237.             END
  238.         ELSIF k0 = {1} THEN (*middle key*)
  239.             IF k1 = {1} THEN (*move*)
  240.                 IF (x0 # x1) OR (y0 # y1) THEN
  241.                     Fd := This(x1, y1); Erase(F);
  242.                     IF Fd = F THEN Graphics.Move(G, x1-x0, y1-y0)
  243.                     ELSIF (Fd # NIL) & (Fd.graph = G) THEN
  244.                         Graphics.Move(G, (x1-Fd.x-x0+F.x) DIV 4 * 4, (y1-Fd.y-y0+F.y) DIV 4 * 4)
  245.                     END ;
  246.                     Draw(F)
  247.                 END
  248.             ELSIF k1 = {1, 2} THEN (*copy*)
  249.                 Fd := This(x1, y1);
  250.                 IF Fd # NIL THEN DrawNorm(F);
  251.                     IF Fd = F THEN Graphics.Copy(G, G, x1-x0, y1-y0)
  252.                     ELSE Deselect(Fd);
  253.                         Graphics.Copy(G, Fd.graph, (x1-Fd.x-x0+F.x) DIV 4 * 4, (y1-Fd.y-y0+F.y) DIV 4 * 4)
  254.                     END ;
  255.                     Draw(Fd)
  256.                 END
  257.             ELSIF k1 = {1, 0} THEN (*shift graph origin*)
  258.                 INC(F.Xg, x1-x0); INC(F.Yg, y1-y0); Restore(F)
  259.             END
  260.         ELSIF k0 = {0} THEN (*right key: select*)
  261.             newcap := NIL;
  262.             IF (ABS(x0-x1) < 7) & (ABS(y0-y1) < 7) THEN
  263.                 IF ~(2 IN k1) THEN Deselect(F) END ;
  264.                 obj := Graphics.ThisObj(G, x1 - F.x, y1 - F.y);
  265.                 IF obj # NIL THEN
  266.                     Graphics.SelectObj(G, obj); DrawObj(F, obj);
  267.                     IF (k1 = {0, 1}) & (obj IS Graphics.Caption) THEN
  268.                         SendCaption(obj(Graphics.Caption))
  269.                     END
  270.                 END
  271.             ELSE Deselect(F);
  272.                 IF x1 < x0 THEN t := x0; x0 := x1; x1 := t END ;
  273.                 IF y1 < y0 THEN t := y0; y0 := y1; y1 := t END ;
  274.                 Graphics.SelectArea(G, x0 - F.x, y0 - F.y, x1 - F.x, y1 - F.y); Draw(F)
  275.             END
  276.         END
  277.     END Edit;
  278.     PROCEDURE NewCaption(F: Frame; col: INTEGER; font: Fonts.Font);
  279.     BEGIN Texts.Write(W, 0DX);
  280.         NEW(newcap); newcap.x := F.mark.x - F.x; newcap.y := F.mark.y - F.y + font.minY;
  281.         newcap.w := 0; newcap.h := font.height; newcap.col := col;
  282.         newcap.pos := SHORT(Graphics.T.len + 1); newcap.len := 0;
  283.         newcap.do := Graphics.CapMethod; Graphics.Add(F.graph, newcap); W.fnt := font
  284.     END NewCaption;
  285.     PROCEDURE InsertChar(F: Frame; ch: CHAR);
  286.         VAR w1, h1: INTEGER; DM: DispMsg;
  287.     BEGIN DM.graph := F.graph;
  288.         Display.GetChar(W.fnt.raster, ch, DM.w, DM.x1, DM.y1, w1, h1, DM.pat); DEC(DM.y1, W.fnt.minY);
  289.         IF newcap.x + newcap.w + DM.w + F.x < F.X1 THEN
  290.             Viewers.Broadcast(DM); INC(newcap.w, DM.w); INC(newcap.len); Texts.Write(W, ch)
  291.         END ;
  292.         Texts.Append(Graphics.T, W.buf)
  293.     END InsertChar;
  294.     PROCEDURE DeleteChar(F: Frame);
  295.         VAR w1, h1: INTEGER; ch: CHAR; pos: LONGINT;
  296.             DM: DispMsg; R: Texts.Reader;
  297.     BEGIN DM.graph := F.graph;
  298.         IF newcap.len > 0 THEN
  299.             pos := Graphics.T.len; Texts.OpenReader(R, Graphics.T, pos-1);  (*backspace*)
  300.             Texts.Read(R, ch);
  301.             IF ch >= " " THEN
  302.                 Display.GetChar(R.fnt.raster, ch, DM.w, DM.x1, DM.y1, w1, h1, DM.pat);
  303.                 DEC(newcap.w, DM.w); DEC(newcap.len); DEC(DM.y1, R.fnt.minY);
  304.                 Viewers.Broadcast(DM); Texts.Delete(Graphics.T, pos-1, pos)
  305.             END
  306.         END
  307.     END DeleteChar;
  308.     PROCEDURE GetSelection(F: Frame; VAR text: Texts.Text; VAR beg, end, time: LONGINT);
  309.         VAR obj: Graphics.Object;
  310.     BEGIN obj := F.graph.sel;
  311.         IF (obj # NIL) & (obj IS Graphics.Caption) & (F.graph.time >= time) THEN
  312.             WITH obj: Graphics.Caption DO beg := obj.pos; end := obj.pos + obj.len END ;
  313.             text := Graphics.T; time := F.graph.time
  314.         END
  315.     END GetSelection;
  316.     PROCEDURE Handle*(G: Display.Frame; VAR M: Display.FrameMsg);
  317.         VAR x, y: INTEGER;
  318.             DM: DispMsg; dM: DrawMsg;
  319.             G1: Frame;
  320.         PROCEDURE move(G: Frame; dx, dy: INTEGER);
  321.             VAR M: UpdateMsg;
  322.         BEGIN Defocus(G); Oberon.FadeCursor(Oberon.Mouse);
  323.             M.id := drawdel; M.graph := G.graph;  Viewers.Broadcast(M);
  324.             Graphics.Move(G.graph, dx, dy); M.id := drawsel; Viewers.Broadcast(M)
  325.         END move;
  326.     BEGIN
  327.         WITH G: Frame DO
  328.             IF M IS Oberon.InputMsg THEN
  329.                 WITH M: Oberon.InputMsg DO
  330.                     IF M.id = Oberon.track THEN
  331.                         x := M.X - (M.X - G.x) MOD 4; y := M.Y - (M.Y - G.y) MOD 4;
  332.                         IF M.keys # {} THEN Edit(G, x, y, M.keys)
  333.                         ELSE Oberon.DrawCursor(Oberon.Mouse, Crosshair, x, y)
  334.                         END
  335.                     ELSIF M.id = Oberon.consume THEN
  336.                         IF M.ch = 7FX THEN
  337.                             IF newcap # NIL THEN DeleteChar(G)
  338.                             ELSE Oberon.FadeCursor(Oberon.Mouse); Defocus(G); Erase(G); Graphics.Delete(G.graph)
  339.                             END
  340.                         ELSIF M.ch = 91X THEN Restore(G)
  341.                         ELSIF M.ch = 93X THEN G.Xg := -1; G.Yg := 0; Restore(G)  (*reset*)
  342.                         ELSIF M.ch = 0C1X THEN move(G, 0, 1)
  343.                         ELSIF M.ch = 0C2X THEN move(G, 0, -1)
  344.                         ELSIF M.ch = 0C3X THEN move(G, 1, 0)
  345.                         ELSIF M.ch = 0C4X THEN move(G, -1, 0)
  346.                         ELSIF (M.ch >= 20X) & (M.ch <= 96X) OR (M.ch = 0ABX) THEN    (* << RC *)
  347.                             IF newcap # NIL THEN InsertChar(G, M.ch)
  348.                             ELSIF G.marked THEN
  349.                                 Defocus(G); Deselect(G); NewCaption(G, M.col, M.fnt); InsertChar(G, M.ch)
  350.                             END
  351.                         END
  352.                     END
  353.                 END
  354.             ELSIF M IS UpdateMsg THEN
  355.                 WITH M: UpdateMsg DO
  356.                     IF M.graph = G.graph THEN
  357.                         dM.f := G; dM.x := G.x; dM.y := G.y; dM.col := 0;
  358.                         CASE M.id OF
  359.                           restore: Restore(G)
  360.                         | drawobj:  dM.mode := 0; M.obj.do.draw(M.obj, dM)
  361.                         | drawobjs: dM.mode := 1; M.obj.do.draw(M.obj, dM)
  362.                         | drawobjd: dM.mode := 3; M.obj.do.draw(M.obj, dM)
  363.                         | drawsel:  dM.mode := 0; Graphics.DrawSel(G.graph, dM)
  364.                         | drawnorm: dM.mode := 2; Graphics.DrawSel(G.graph, dM)
  365.                         | drawdel:  dM.mode := 3; Graphics.DrawSel(G.graph, dM)
  366.                         END
  367.                     END
  368.                 END
  369.             ELSIF M IS SelQuery THEN
  370.                 WITH M: SelQuery DO
  371.                     IF (G.graph.sel # NIL) & (M.time < G.graph.time) THEN
  372.                         M.f := G; M.time := G.graph.time
  373.                     END
  374.                 END
  375.             ELSIF M IS FocusQuery THEN
  376.                 IF G.marked THEN M(FocusQuery).f := G END
  377.             ELSIF M IS PosQuery THEN
  378.                 WITH M: PosQuery DO
  379.                     IF (G.X <= M.x) & (M.x < G.X1) & (G.Y <= M.y) & (M.y < G.Y1) THEN M.f := G END
  380.                 END
  381.             ELSIF M IS DispMsg THEN
  382.                 DM := M(DispMsg);
  383.                 x := G.x + newcap.x + newcap.w; y := G.y + newcap.y;
  384.                 IF (DM.graph = G.graph) & (x >= G.X) & (x + DM.w < G.X1) & (y >= G.Y) & (y < G.Y1) THEN
  385.                     Display.CopyPattern(Oberon.CurCol, DM.pat, x + DM.x1, y + DM.y1, 2);
  386.                     Display.ReplConst(Display.white, x, y, DM.w, newcap.h, 2)
  387.                 END
  388.             ELSIF M IS Oberon.ControlMsg THEN
  389.                 WITH M: Oberon.ControlMsg DO
  390.                     IF M.id = Oberon.neutralize THEN
  391.                         Oberon.RemoveMarks(G.X, G.Y, G.W, G.H); Defocus(G);
  392.                         DrawNorm(G); Graphics.Deselect(G.graph)
  393.                     ELSIF M.id = Oberon.defocus THEN Defocus(G)
  394.                     END
  395.                 END
  396.             ELSIF M IS Oberon.SelectionMsg THEN
  397.                 WITH M: Oberon.SelectionMsg DO GetSelection(G, M.text, M.beg, M.end, M.time) END
  398.             ELSIF M IS Oberon.CopyMsg THEN
  399.                 Oberon.RemoveMarks(G.X, G.Y, G.W, G.H); Defocus(G);
  400.                 NEW(G1); G1^ := G^; M(Oberon.CopyMsg).F := G1
  401.             ELSIF M IS MenuViewers.ModifyMsg THEN
  402.                 WITH M: MenuViewers.ModifyMsg DO G.Y := M.Y; G.H := M.H; Restore(G) END
  403.             ELSIF M IS Oberon.CopyOverMsg THEN
  404.                 WITH M: Oberon.CopyOverMsg DO
  405.                     IF G.marked THEN
  406.                         DrawObj(G, CaptionCopy(G, G.mark.x, G.mark.y, M.text, M.beg, M.end))
  407.                     END
  408.                 END
  409.             END
  410.         END
  411.     END Handle;
  412.     (*------------------- Methods -----------------------*)
  413.     PROCEDURE DrawLine(obj: Graphics.Object; VAR M: Graphics.Msg);
  414.         (*M.mode = 0: draw according to state,
  415.                 = 1: normal -> selected,
  416.                 = 2: selected -> normal,
  417.                 = 3: erase*)
  418.         VAR x, y, w, h, col: INTEGER; f: Frame;
  419.     BEGIN 
  420.         WITH M: DrawMsg DO
  421.             x := obj.x + M.x; y := obj.y + M.y; w := obj.w; h := obj.h; f := M.f;
  422.             IF (x+w > f.X) & (x < f.X1) & (y+h > f.Y) & (y < f.Y1) THEN
  423.                 IF M.col = Display.black THEN col := obj.col ELSE col := M.col (*macro*) END ;
  424.                 IF (M.mode = 0) & obj.selected OR (M.mode = 1) THEN
  425.                     Display.ReplPatternC(f, col, Display.grey2, x, y, w, h, x, y, 0)
  426.                 ELSIF M.mode = 3 THEN Display.ReplConstC(f, Display.black, x, y, w, h, 0)  (*erase*)
  427.                 ELSE Display.ReplConstC(f, col, x, y, w, h, 0)
  428.                 END
  429.             END
  430.         END
  431.     END DrawLine;
  432.     PROCEDURE DrawCaption(obj: Graphics.Object; VAR M: Graphics.Msg);
  433.         VAR x, y, dx, x0, x1, y0, y1, w, h, w1, h1, col: INTEGER;
  434.             f: Frame;
  435.             ch: CHAR; pat: Display.Pattern; fnt: Fonts.Font;
  436.             R: Texts.Reader;
  437.     BEGIN
  438.         WITH M: DrawMsg DO
  439.             x := obj.x + M.x; y := obj.y + M.y; w := obj.w; h := obj.h; f := M.f;
  440.             IF (f.X <= x) & (x <= f.X1) & (f.Y <= y) & (y+h <= f.Y1) THEN
  441.                 IF x+w > f.X1 THEN w := f.X1-x END ;
  442.                 Texts.OpenReader(R, Graphics.T, obj(Graphics.Caption).pos); Texts.Read(R, ch);
  443.                 IF M.mode = 0 THEN
  444.                     IF ch >= " " THEN
  445.                         IF M.col = Display.black THEN col := obj.col ELSE col := M.col (*macro*) END ;
  446.                         fnt := R.fnt; x0 := x; y0 := y - fnt.minY;
  447.                         LOOP
  448.                             Display.GetChar(fnt.raster, ch, dx, x1, y1, w1, h1, pat);
  449.                             IF x0+x1+w1 <= f.X1 THEN Display.CopyPattern(col, pat, x0+x1, y0+y1, 1) ELSE EXIT END ;
  450.                             INC(x0, dx); Texts.Read(R, ch);
  451.                             IF ch < " " THEN EXIT END
  452.                         END ;
  453.                         IF obj.selected THEN Display.ReplConst(Display.white, x, y, w, h, 2) END
  454.                     END
  455.                 ELSIF M.mode < 3 THEN Display.ReplConst(Display.white, x, y, w, h, 2)
  456.                 ELSE Display.ReplConst(Display.black, x, y, w, h, 0)
  457.                 END
  458.             END
  459.         END
  460.     END DrawCaption;
  461.     PROCEDURE DrawMacro(obj: Graphics.Object; VAR M: Graphics.Msg);
  462.         VAR x, y, w, h: INTEGER;
  463.             f: Frame; M1: DrawMsg;
  464.     BEGIN
  465.         WITH M: DrawMsg DO
  466.             x := obj.x + M.x; y := obj.y + M.y; w := obj.w; h := obj.h; f := M.f;
  467.             IF (x+w > f.X) & (x < f.X1) & (y+h > f.Y) & (y < f.Y1) THEN
  468.                 M1.x := x; M1.y := y;
  469.                 IF M.mode = 0 THEN
  470.                     M1.f := f; M1.col := obj.col; M1.mode := 0; Graphics.DrawMac(obj(Graphics.Macro).mac, M1);
  471.                     IF obj.selected THEN Display.ReplConstC(f, Display.white, x, y, w, h, 2) END
  472.                 ELSIF M.mode < 3 THEN Display.ReplConstC(f, Display.white, x, y, w, h, 2)
  473.                 ELSE Display.ReplConstC(f, Display.black, x, y, w, h, 0)
  474.                 END
  475.             END
  476.         END
  477.     END DrawMacro;
  478.     (*---------------------------------------------------------------*)
  479.     PROCEDURE Open*(G: Frame; graph: Graphics.Graph; X, Y, col: INTEGER; ticked: BOOLEAN); 
  480.     BEGIN G.graph := graph; G.Xg := X; G.Yg := Y; G.col := col; G.marked := FALSE;
  481.         G.mark.next := NIL; G.ticked := ticked; G.handle := Handle
  482.     END Open;
  483.     PROCEDURE DrawCrosshair(x, y: INTEGER);
  484.     BEGIN
  485.         IF x < CL THEN
  486.             IF x < markW THEN x := markW ELSIF x > DW THEN x := DW - markW END
  487.         ELSE
  488.             IF x < CL + markW THEN x := CL + markW ELSIF x > CL + DW THEN x := CL + DW - markW END
  489.         END ;
  490.         IF y < markW THEN y := markW ELSIF y > DH THEN y := DH - markW END ;
  491.         Display.CopyPattern(Display.white, Display.cross, x - markW, y - markW, 2)
  492.     END DrawCrosshair;
  493. BEGIN DW := Display.Width - 8; DH := Display.Height - 8; CL := Display.ColLeft;
  494.     Crosshair.Draw := DrawCrosshair; Crosshair.Fade := DrawCrosshair; Texts.OpenWriter(W);
  495.     Graphics.LineMethod.draw := DrawLine; Graphics.CapMethod.draw := DrawCaption;
  496.     Graphics.MacMethod.draw := DrawMacro
  497. END GraphicFrames.
  498.